package com.jeequan.jeepay.mch.ctrl.anon;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.JeepayClient;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.MchApp;
import com.jeequan.jeepay.core.entity.PayInterfaceConfig;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.DBApplicationConfig;
import com.jeequan.jeepay.core.utils.DisResultHttp;
import com.jeequan.jeepay.core.utils.DistResult;
import com.jeequan.jeepay.exception.JeepayException;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.mch.websocket.server.WsPayOrderServer;
import com.jeequan.jeepay.model.PayOrderCreateReqModel;
import com.jeequan.jeepay.request.PayOrderCreateRequest;
import com.jeequan.jeepay.response.PayOrderCreateResponse;
import com.jeequan.jeepay.service.impl.MchAppService;
import com.jeequan.jeepay.service.impl.PayInterfaceConfigService;
import com.jeequan.jeepay.service.impl.SysConfigService;

import com.jeequan.jeepay.util.JeepayKit;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.logging.Log;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

@Tag(name = "支付模块")
@RestController
@RequestMapping("/api/anon/pay")
public class PayController extends CommonCtrl {
    @Autowired
    private PayInterfaceConfigService payInterfaceConfigService;
    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private MchAppService mchAppService;

    /** 查询当前应用支持的支付接口 */
    @Operation(summary = "查询当前应用支持的支付接口")
    @Parameters({
            @Parameter(name = "appId", description = "应用ID", required = true)
    })
    @PostMapping("/ifCodes")
    public ApiRes<Set<String>> getIfCodeByAppId() {
        String appId = getValStringRequired("appId");
        MchApp mchApp = mchAppService.getById(appId);
        if(mchApp == null){
            throw new BizException("商户应用不存在");
        }

        Set<String> result = new HashSet<>();

        payInterfaceConfigService.list(PayInterfaceConfig.gw().select(PayInterfaceConfig::getIfCode)
                .eq(PayInterfaceConfig::getState, CS.PUB_USABLE)
                .eq(PayInterfaceConfig::getInfoId, appId)
                .eq(PayInterfaceConfig::getInfoType, CS.INFO_TYPE_MCH_APP)
        ).stream().forEach(r -> result.add(r.getIfCode()));

        return ApiRes.ok(result);
    }

    @Operation(summary ="生成支付数据")
    @Parameters({
            @Parameter(name = "mchOrderNo", description = "商户订单号", required = true),
            @Parameter(name = "appId", description = "应用ID", required = true),
            @Parameter(name = "wayCode", description = "支付方式代码", required = true),
            @Parameter(name = "amount", description = "转账金额,单位元", required = true),
            @Parameter(name = "returnUrl", description = "页面跳转地址", required = true),
            @Parameter(name = "divisionMode", description = "订单分账模式：0-该笔订单不允许分账, 1-支付成功按配置自动完成分账, 2-商户手动分账(解冻商户金额)", required = true),
            @Parameter(name = "orderTitle", description = "订单标题", required = true),
            @Parameter(name = "currency", description = "币种"),
            @Parameter(name = "expiredTime", description = "过期时间"),
            @Parameter(name = "clientIp", description = "客户端IP"),
            @Parameter(name = "notifyUrl", description = "通知地址"),
            @Parameter(name = "channelExtra", description = "特定渠道发起时额外参数"),
            @Parameter(name = "payDataType", description = "支付数据包 类型，eg：form--表单提交，wxapp--微信app参数，aliapp--支付宝app参数，ysfapp--云闪付app参数，codeUrl--二维码URL，codeImgUrl--二维码图片显示URL，none--无参数"),
            @Parameter(name = "authCode", description = "支付条码"),
            @Parameter(name = "successUrl", description = "支付成功跳转地址"),
            @Parameter(name = "failUrl", description = "支付失败跳转地址"),
            @Parameter(name = "cancelUrl", description = "支付取消跳转地址"),
            @Parameter(name = "extParam", description = "扩展参数")
    })
    @PostMapping("/genPayData")
    public ApiRes genPayData() throws IOException {
        //获取请求参数
        String appId = getValStringRequired("appId");
        Long amount = getRequiredAmountL("amount");
        String mchOrderNo = getValStringRequired("mchOrderNo");
        String wayCode = getValStringRequired("wayCode");
        Byte divisionMode = getValByteRequired("divisionMode");
        String orderTitle = getValStringRequired("orderTitle");
        String currency = getValString("currency");
        if(StringUtils.isEmpty(orderTitle)){
            throw new BizException("订单标题不能为空");
        }
        // 前端明确了支付参数的类型 payDataType
        String payDataType = getValString("payDataType");
        String authCode = getValString("authCode");
        String successUrl = getValString("successUrl");
        String failUrl = getValString("failUrl");
        String cancelUrl = getValString("cancelUrl");
        String returnUrl = getValString("returnUrl");
        MchApp mchApp = mchAppService.getById(appId);
        if(mchApp == null || mchApp.getState() != CS.PUB_USABLE || !mchApp.getAppId().equals(appId)){
            throw new BizException("商户应用不存在或不可用");
        }
        PayOrderCreateRequest request = new PayOrderCreateRequest();
        PayOrderCreateReqModel model = new PayOrderCreateReqModel();
        request.setBizModel(model);
        model.setMchNo(mchApp.getMchNo()); // 商户号
        model.setAppId(appId);
        model.setMchOrderNo(mchOrderNo);
        model.setWayCode(wayCode);
        model.setAmount(amount);
        if(StringUtils.isNotBlank(currency)){
            model.setCurrency(currency);
        } else if(wayCode.equalsIgnoreCase("pp_pc") || wayCode.equalsIgnoreCase("air_pc")) {
            model.setCurrency("USD");
        } else {
            model.setCurrency("CNY");
        }
        model.setClientIp(getClientIp());
        model.setSubject(orderTitle);
        model.setBody(orderTitle + "[" + mchApp.getMchNo() + "商户联调]");

        DBApplicationConfig dbApplicationConfig = sysConfigService.getDBApplicationConfig();
        model.setNotifyUrl(dbApplicationConfig.getMchSiteUrl() + "/api/anon/pay/payOrderNotify"); //回调地址
        model.setDivisionMode(divisionMode); //分账模式
        model.setReturnUrl(returnUrl);
        //设置扩展参数
        JSONObject extParams = new JSONObject();
        if(StringUtils.isNotEmpty(payDataType)) {
            extParams.put("payDataType", payDataType.trim());
        }
        if(StringUtils.isNotEmpty(authCode)) {
            extParams.put("authCode", authCode.trim());
        }
        if(StringUtils.isNotEmpty(successUrl)) {
            extParams.put("successUrl", successUrl.trim());
        }
        if(StringUtils.isNotEmpty(failUrl)) {
            extParams.put("failUrl", failUrl.trim());
        }
        if(StringUtils.isNotEmpty(cancelUrl)) {
            extParams.put("cancelUrl", cancelUrl.trim());
        }
        model.setChannelExtra(extParams.toString());
        JeepayClient jeepayClient = new JeepayClient(dbApplicationConfig.getPaySiteUrl(), mchApp.getAppSecret());
        try {
            PayOrderCreateResponse response = jeepayClient.execute(request);
            if(response.getCode() != 0){
                throw new BizException(response.getMsg());
            }
            return ApiRes.ok(response.get());
        } catch (JeepayException e) {
            throw new BizException(e.getMessage());
        }
    }

    @PostMapping("/callback")
    public ApiRes callback() throws IOException {
        logger.debug(JSON.toJSONString(getReqParamJSON()));
        return ApiRes.ok(new String("Success"));
    }

    @Operation(summary = "支付回调信息")
    @Parameters({
            @Parameter(name = "appId", description = "应用ID", required = true),
            @Parameter(name = "mchNo", description = "商户号", required = true),
            @Parameter(name = "sign", description = "签名值", required = true)
    })
    @RequestMapping("/payOrderNotify")
    public void payOrderNotify() throws IOException {

        //请求参数
        JSONObject params = getReqParamJSON();
//        Logger.info("params", params);

        String mchNo = params.getString("mchOrderNo");
//        String amount = params.getString("amount");


        logger.info("验证支付通知数据详情 ---{}", mchNo);
        //推送到前端
        sendHttpsRequest("", mchNo);
        String appId = params.getString("appId");
        String sign = params.getString("sign");
        MchApp mchApp = mchAppService.getById(appId);
        if(mchApp == null || !mchApp.getMchNo().equals(mchNo)){
            response.getWriter().print("app is not exists");
            return;
        }
        logger.info("断断断断断断断断1 ---");
        params.remove("sign");
        if(!JeepayKit.getSign(params, mchApp.getAppSecret()).equalsIgnoreCase(sign)){
            response.getWriter().print("sign fail");
            return;
        }
        logger.info("断断断断断断断断2 ---");
        JSONObject msg = new JSONObject();
        msg.put("state", params.getIntValue("state"));
        msg.put("errCode", params.getString("errCode"));
        msg.put("errMsg", params.getString("errMsg"));
        //https://so.aihubs.cn:19318/api/anon/detail/payOrder
        logger.info("验证支付通知数据{}", params);

        WsPayOrderServer.sendMsgByOrderId(params.getString("payOrderId"), msg.toJSONString());
        response.getWriter().print("SUCCESS");
    }

    void sendHttpsRequest(String amount, String mchNo) {
        logger.info("发送数据{}", mchNo);
        try {
            HashMap<String, Object> map = new HashMap<>();
            map.put("mchOrderNo", mchNo);
            map.put("amount", "100");
            DistResult  result = DisResultHttp.doPostHttpsAir(
                    "https://so.aihubs.cn:18080/api/v1/orders/paymentNotice", map,"", "");
        }catch (Exception e) {
            e.printStackTrace();
            logger.info("验证支付通知数据----ERR");
        }
    }

}


